package main

import (
	"fmt"
	"log"

	"github.com/streadway/amqp"
)

// 消费者函数，负责接收消息并打印
func consumeMessages(ch *amqp.Channel, done chan bool) {
	// 声明交换机
	err := ch.ExchangeDeclare(
		"chat_group", // 交换机名称
		"fanout",     // 交换机类型
		true,         // 是否持久化
		false,        // 是否自动删除
		false,        // 是否等待消费者
		false,        // 是否等待消费者
		nil,          // 额外参数
	)
	if err != nil {
		log.Fatal(err)
	}

	// 声明队列（使用匿名队列）
	q, err := ch.QueueDeclare(
		"",    // 自动生成一个临时队列
		false, // 是否持久化
		false, // 是否自动删除
		true,  // 是否独占
		false, // 是否等待消费者
		nil,   // 额外参数
	)
	if err != nil {
		log.Fatal(err)
	}

	// 将队列绑定到交换机
	err = ch.QueueBind(
		q.Name,       // 队列名称
		"",           // 路由键为空（fanout广播消息）
		"chat_group", // 交换机名称
		false,        // 是否等待消费者
		nil,          // 额外参数
	)
	if err != nil {
		log.Fatal(err)
	}

	// 开始消费消息
	msgs, err := ch.Consume(
		q.Name, // 队列名称
		"",     // 消费者名称
		true,   // 自动确认
		false,  // 独占
		false,  // 不阻塞
		false,  // 额外参数
		nil,
	)
	if err != nil {
		log.Fatal(err)
	}

	// 打印接收到的消息
	for msg := range msgs {
		log.Printf(" [x] Received from %s: %s", msg.Headers["Sender"], msg.Body)
	}
}

func main() {
	// 提示用户输入自己的标识符（用户名或ID）
	fmt.Println("Enter your username:")
	var username string
	_, err := fmt.Scanln(&username)
	if err != nil {
		log.Fatal(err)
	}

	// 连接到RabbitMQ服务器
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()

	// 创建一个频道
	ch, err := conn.Channel()
	if err != nil {
		log.Fatal(err)
	}
	defer ch.Close()

	// 创建一个接收消息的协程
	done := make(chan bool)
	go consumeMessages(ch, done)

	// 循环等待用户输入
	for {
		// 提示用户输入消息
		fmt.Println("Enter a message to send to the group chat (type 'exit' to quit):")
		var message string
		_, err := fmt.Scanln(&message)
		if err != nil {
			log.Fatal(err)
		}

		// 如果用户输入 "exit"，则退出循环
		if message == "exit" {
			log.Println("Exiting the program...")
			close(done)
			break
		}

		// 发送群聊消息，并附带发送者的标识
		err = ch.Publish(
			"chat_group", // 交换机名称
			"",           // 路由键为空（fanout交换机会广播消息）
			false,        // 是否持久化
			false,        // 是否确认
			amqp.Publishing{
				ContentType: "text/plain",
				Body:        []byte(message),
				Headers:     amqp.Table{"Sender": username}, // 在消息头部附加发送者的标识
			},
		)
		if err != nil {
			log.Fatal(err)
		}

		log.Printf(" [x] Sent from %s: %s", username, message)
	}
}
